package com.weishaoying.rws.aspect;

import com.weishaoying.rws.annotation.DataSource;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author WeiShaoying
 * @date 2018/5/5
 */
@Aspect
@Component
@EnableAspectJAutoProxy//(proxyTargetClass = true)
public class DataSourceAspect {

    protected Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);

    @Pointcut("execution(* com.weishaoying.rws.service.*.*(..))")
    public void rws() {
    }

    @Before("rws()")
    public void before(JoinPoint point) {
        System.out.println("========切面拦截开始");
        String className = point.getTarget().getClass().getName();
        String methodName = point.getSignature().getName();
        System.out.println("========请求方法：" + className + "." + methodName + "(" + StringUtils.join(point.getArgs(), ",") + ")");

        try {
            //遍历Map,其实只有2个Read/Write
            for (String key : ChooseDataSource.METHOD_TYPE_MAP.keySet()) {
                //通过key获得value，value是List所以遍历
                for (String type : ChooseDataSource.METHOD_TYPE_MAP.get(key)) {
                    //如果方法名等于type
                    if (methodName.startsWith(type)) {
                        System.out.println("========" + methodName + " start with " + type + ", Use " + key + " DataSource");
                        //把read/write放到ThreadLocal中
                        DataSourceHolder.putDataSource(key);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //另外一种方式,通过方法上的注解来判断使用哪种数据源
    public void before2(JoinPoint point) {
        Object target = point.getTarget();
        System.out.println(target.toString());
        String method = point.getSignature().getName();
        System.out.println(method);
        Class<?> classz = target.getClass();
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature()).getMethod().getParameterTypes();
        try {
            Method m = classz.getMethod(method, parameterTypes);
            System.out.println(m.getName());
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource dataSource = m.getAnnotation(DataSource.class);
                DataSourceHolder.putDataSource(dataSource.value());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
